/**
 * @file app_main.c
 * @brief 主线程
 *
 * @author 钟涛
 *
 * @date 2022-05-08
 *
 * @copyright 海南大学 - 追光者
 */

#include <rtthread.h>
#include <rtdevice.h>
#include "drv_common.h"
#include "app_main.h"

#include "app_bh1750.h"
#include "DHT11.h"
#include "motor.h"
#include "mpu6050.h"
#include "mc907.h"
#include "l610.h"
#include "sr04.h"
#include "lcd.h"
#include "app_sgp30.h"

#define DBG_TAG "main"
#define DBG_LVL DBG_INFO
#include <rtdbg.h>

extern uint8_t disease[18];

int g_USART1_FLAG1 = 0;
uint8_t flag_work, flag_scan;
uint16_t timer_scan;
uint16_t pwm_val;
int16_t previous_yaw;
int16_t present_yaw;
int16_t Difference_yaw;
float pitch, roll, yaw;
uint8_t send_dat[200];
uint16_t send_time = 0, update_time = 0, sensor_time = 0;
uint16_t pwm_val = 0;
uint8_t c = 0;
uint32_t sgp30_dat;
rt_event_t s_event;
uint8_t temperature = 27, humidity = 69;
int16_t CO2 = 400, VOC;
int distance1, distance2, distance3;
float light = 2000;

static uint8_t publish_message[800];

/**
 * 上传属性到搭建的平台
 */
void mqtt_upload_recv_thread(void *params)
{
    while (1)
    {
        rt_uint32_t e = 0;

        rt_event_recv(s_event,
        EVENT_UPLOAD_DHT | EVENT_UPLOAD_LIGHT | EVENT_UPLOAD_CO2VOC | EVENT_UPLOAD_YAW,
        RT_EVENT_FLAG_CLEAR | RT_EVENT_FLAG_OR, RT_WAITING_FOREVER, &e);
        LOG_D("upload recv event: %08X", e);

        // 拼接JSON
        sprintf(publish_message, "{\"id\": 123,\"dp\": {");
        sprintf(publish_message + strlen(publish_message), "\"disease\": [{\"v\": \"%s\"}]", disease);
        if (e & EVENT_UPLOAD_DHT)
        {
            sprintf(publish_message + strlen(publish_message),
                    ",\"temperature\":[{\"v\":%d}],\"humidity\": [{\"v\":%d}],\"humidity2\":[{\"v\":%d}]", temperature,
                    humidity, humidity);
        }
        if (e & EVENT_UPLOAD_LIGHT)
        {
            sprintf(publish_message + strlen(publish_message), ",\"light\":[{\"v\":%.1f}]", light);
        }
        if (e & EVENT_UPLOAD_CO2VOC)
        {
            sprintf(publish_message + strlen(publish_message), ",\"CO2\": [{\"v\":%u}],\"VOC\":[{\"v\":%u}]", CO2, VOC);
        }
        if (e & EVENT_UPLOAD_YAW)
        {
            sprintf(publish_message + strlen(publish_message), ",\"yaw\":[{\"v\":%.1f}],\"distance\":[{\"v\":%d}]", yaw,
                    distance1);
        }
        strcat(publish_message, "}}");
        LOG_I("publish_message: %s", publish_message);
#ifdef APP_USING_NBIOT
        nbiot_mqtt_publish(publish_message);
#elif defined(APP_USING_L610)
        l610_mqtt_publish(publish_message);
#endif
    }
}

/**
 * 上传数据到onenet平台
 * @param params 无
 */
void upload_thread(void *params)
{
    while (1)
    {
        sprintf((char *) send_dat, "AT+MIPLNOTIFY=0,29980,3324,0,5700,4,8,%u,0,0,1\r\n", VOC);        //TVOC
        rt_device_write(dev_nbiot, 0, send_dat, strlen((const char *) send_dat));
        rt_thread_mdelay(2800);
        sprintf((char *) send_dat, "AT+MIPLNOTIFY=0,29980,3200,0,5751,1,18,%s,0,0,1\r\n", disease);        //病虫害信息
        rt_device_write(dev_nbiot, 0, send_dat, strlen((const char *) send_dat));
        rt_thread_mdelay(2800);
        sprintf((char *) send_dat, "AT+MIPLNOTIFY=0,29980,3325,0,5750,1,3,%u,0,0,1\r\n", CO2);        //CO2
        rt_device_write(dev_nbiot, 0, send_dat, strlen((const char *) send_dat));
        rt_thread_mdelay(2800);
        sprintf((char *) send_dat, "AT+MIPLNOTIFY=0,29980,3200,0,5501,3,2,%d,0,0,1\r\n", temperature); //温度
        rt_device_write(dev_nbiot, 0, send_dat, strlen((const char *) send_dat));
        rt_thread_mdelay(2800);
        sprintf((char *) send_dat, "AT+MIPLNOTIFY=0,29980,3200,0,5505,3,2,%d,0,0,1\r\n", humidity);        //湿度
        rt_device_write(dev_nbiot, 0, send_dat, strlen((const char *) send_dat));
        rt_thread_mdelay(2800);
        sprintf((char *) send_dat, "AT+MIPLNOTIFY=0,29980,3301,0,5700,4,8,%f,0,0,1\r\n", light);        //光照强度
        rt_device_write(dev_nbiot, 0, send_dat, strlen((const char *) send_dat));
        rt_thread_mdelay(2800);
    }
}

/**
 * 定时测量线程
 * @param params 无
 */
void measure_thread(void *params)
{
    while (1)
    {
        uint32_t e = 0;
        light = bh1750_read_light(hdev);
        LOG_D("light: %d, distance: %d, %d, %d", (int )light, distance1, distance2, distance3);

        if (DHT11_Read(&temperature, &humidity))
        {
            LOG_E("Read DHT11 fail!");
        }
        else
        {
            LOG_D("temperature: %u °C, humidity: %u %%", temperature, humidity);
            e |= EVENT_UPLOAD_DHT;
        }

        if (sgp30_read(&CO2, &VOC))
        {
            LOG_D("CO2: %d, VOC: %d", CO2, VOC);
            e |= EVENT_UPLOAD_CO2VOC;
        }
        else
        {
            LOG_E("read sgp30 fail.");
        }
        rt_event_send(s_event, e | EVENT_UPLOAD_LIGHT | EVENT_UPLOAD_YAW);
        rt_thread_mdelay(5000);
    }
}

/**
 * 测距线程
 * @param params 无
 */
void measure_distance(void *params)
{
    while (1)
    {
        distance1 = sr04_measure(SR04_NUM1);
        distance2 = sr04_measure(SR04_NUM2);
        distance3 = sr04_measure(SR04_NUM3);
        if (distance1 > 0 && distance1 < 10)
        {
            rt_pin_write(BEEP_PIN, BEEP_ON);
            distance_stop();
        }
        else
        {
            rt_pin_write(BEEP_PIN, BEEP_OFF);
        }
        rt_thread_mdelay(40);
    }
}

/**
 * 主函数
 * @return 0
 */
int main(void)
{
    rt_thread_t thread;

    thread = rt_thread_create("measure", measure_thread, NULL, 2048, PRIO_UPLOAD, 10);
    rt_thread_startup(thread);

#if defined(APP_USING_NBIOT) || defined(APP_USING_L610)
#ifdef APP_USING_MQTT
    thread = rt_thread_create("upload_recv", mqtt_upload_recv_thread, NULL, 2048, PRIO_UPLOAD_RECV, 10);
    rt_thread_startup(thread);
#else
    thread = rt_thread_create("upload", upload_thread, NULL, 2048, PRIO_UPLOAD, 10);
    rt_thread_startup(thread);
#endif
#endif

    thread = rt_thread_create("distance", measure_distance, NULL, 2048, PRIO_DISTANCE, 10);
    rt_thread_startup(thread);

#ifdef APP_USING_LCD
    char sprintfBuff[500];
#endif

    previous_yaw = yaw;

    while (1)
    {
        rt_uint32_t e = 0;
        rt_event_recv(s_event, EVENT_NBIOT_MQTT_READY, RT_EVENT_FLAG_OR, 0, &e);

#ifdef APP_USING_LCD
        LCD_ShowString(40, 10, 500, 24, 24, "Intelligent Agricultural Studio of");
        LCD_ShowString(130, 40, 500, 24, 24, " Hainan University");

        sprintf((char*) sprintfBuff, "temperature: %d CEL", temperature);
        LCD_ShowString(30, 100, 220, 24, 24, sprintfBuff);

        sprintf((char*) sprintfBuff, "humidity: %d RH", humidity);
        LCD_ShowString(30, 130, 200, 24, 24, sprintfBuff);

        sprintf((char*) sprintfBuff, "soil_humidity: %d RH", humidity);
        LCD_ShowString(30, 160, 200, 24, 24, sprintfBuff);

        sprintf((char*) sprintfBuff, "light: %f lx", light);
        LCD_ShowString(30, 190, 200, 24, 24, sprintfBuff);

        sprintf((char*) sprintfBuff, "CO2: %d ppm", CO2);
        LCD_ShowString(30, 220, 200, 24, 24, sprintfBuff);

        sprintf((char*) sprintfBuff, "TVOC: %d ppb", VOC);
        LCD_ShowString(30, 250, 200, 24, 24, sprintfBuff);

        sprintf((char*) sprintfBuff, "Disease: %s", disease);
        LCD_ShowString(30, 330, 340, 24, 24, sprintfBuff);

        sprintf((char*) sprintfBuff, "yaw: %f", yaw);
        LCD_ShowString(30, 430, 200, 24, 24, sprintfBuff);

        sprintf((char*) sprintfBuff, "pitch: %f", pitch);
        LCD_ShowString(30, 460, 200, 24, 24, sprintfBuff);

        sprintf((char*) sprintfBuff, "roll: %f", roll);
        LCD_ShowString(30, 490, 200, 24, 24, sprintfBuff);

        sprintf((char*) sprintfBuff, "Distance: %3d %3d %3d cm", distance1, distance2, distance3);
        LCD_ShowString(30, 520, 340, 24, 24, sprintfBuff);

        sprintf((char*) sprintfBuff, "mqtt status: %-15s", (e & EVENT_NBIOT_MQTT_READY) ? "ready" : "connecting...");
        LCD_ShowString(30, 550, 340, 24, 24, sprintfBuff);
#endif

        rt_thread_mdelay(500);

        e = 0;
        rt_event_recv(s_event, EVENT_PRESS_KEY0 | EVENT_PRESS_KEY1 | EVENT_PRESS_KEY2, RT_EVENT_FLAG_OR, 0, &e);

        if (e & EVENT_PRESS_KEY0)
        {
            LOG_I("press KEY0");
        }
        if (e & EVENT_PRESS_KEY1)
        {
            LOG_I("press KEY1");
        }
        if (e & EVENT_PRESS_KEY2)
        {
            LOG_I("press KEY2");
        }

        // ...
    }

    return RT_EOK;
}

void test_beep(void)
{
    rt_pin_write(BEEP_PIN, BEEP_ON);
    rt_thread_mdelay(1000);
    rt_pin_write(BEEP_PIN, BEEP_OFF);
}
MSH_CMD_EXPORT(test_beep, test beep);

int app_prev_init(void)
{
    s_event = rt_event_create("s_event", RT_IPC_FLAG_PRIO);

    rt_pin_mode(BEEP_PIN, PIN_MODE_OUTPUT);
    rt_pin_write(BEEP_PIN, BEEP_OFF);

    return 0;
}
INIT_PREV_EXPORT(app_prev_init);

struct serial_configure debug_uart_config = RT_SERIAL_CONFIG_DEFAULT; /* 初始化配置参数 */
int debug_uart_init(void)
{
    rt_device_t dev_uart = rt_device_find(RT_CONSOLE_DEVICE_NAME);
    debug_uart_config.baud_rate = BAUD_RATE_921600;        //修改波特率
    /* step3：控制串口设备。通过控制接口传入命令控制字，与控制参数 */
    rt_device_control(dev_uart, RT_DEVICE_CTRL_CONFIG, &debug_uart_config);

    return 0;
}
INIT_BOARD_EXPORT(debug_uart_init);
